from querier.esquerier import ElasticSearchQuerier
import utils
import math
from querier.wechat.article_get_keywords import WechatGetKeywordsQuerier

MAX_LEN = 200

MINIMUM_SHOULD_MATCH = '5<85% 10<9'
MAX_CHARACTER = 5


class WechatRecommendQuerier(ElasticSearchQuerier):
    def __init__(self, es, index, doc_type, index_selected, doc_type_selected, nlp_service):
        super(WechatRecommendQuerier, self).__init__(None, None, None)
        self.getKeywordsQuerier = WechatGetKeywordsQuerier(es, index, doc_type)
        self.articleMatchQuerier = WechatArticleMatchQuerier(es, index_selected, doc_type_selected)
        self.nlp_service = nlp_service

    def search(self, args):
        ids = args.get('ids', None)
        if not ids:
            ids = []

        push_ids = args.get('push_ids', None)
        if not push_ids:
            push_ids = []

        size = args.get('size', 12)
        if not size:
            size = 12
        from_ = args.get('from', 0)
        if not size:
            from_ = 0

        filters = args.get('filters', None)
        if not filters:
            filters = {}

        if not ids:
            filters['selected'] = ['t']

        res = self.getKeywordsQuerier.search({"ids": ids})
        categories = res.get('categories', [])
        keywords = res.get('keywords', [])

        out = self.articleMatchQuerier.search(
                {'push_ids': push_ids + ids, 'keywords': keywords[0: MAX_LEN], 'categories': categories[0:MAX_LEN],
                 'filters': filters, "size": size, 'from': from_})
        return out

    def _build_query(self, args):
        pass

    def _build_result(self, es_result, param):
        pass


class WechatArticleMatchQuerier(ElasticSearchQuerier):
    def __init__(self, es, index, doc_type):
        super(WechatArticleMatchQuerier, self).__init__(es, index, doc_type)

    def _build_query(self, args):
        keywords = args.get('keywords', None)
        if not keywords:
            keywords = []
        categories = args.get('categories', None)
        if not categories:
            categories = []

        filters = args.get('filters', {})
        if not filters:
            filters = {}
        size = args.get('size', 12)
        if not size:
            size = 12
        from_ = args.get('from', 0)
        if not size:
            from_ = 0

        ids = args.get('push_ids', None)
        if not ids:
            ids = []

        query = self._genQuery(keywords, categories, filters, ids, from_, size)
        return query, {}, {'keywords': keywords, 'categories': categories, "filters": filters}

    def _build_result(self, es_result, param):
        keywords = param['keywords']
        keywords.sort()
        total = es_result['hits']['total']
        posts = []
        for hit in es_result['hits']['hits']:
            posts.append(extractResult(hit))
        return {
            'total': total,
            'filters': param['filters'],
            'keywords': keywords,
            'categories': param['categories'],
            'articles': posts
        }

    def _addFilterClause(self, filter_clause, filters, key, cond='must'):
        if key in filters:
            if filters[key]:
                clause = []
                filter_clause.append({
                    'bool': {
                        cond: clause
                    }
                })
                for fk in filters[key]:
                    clause.append({'term': {key: fk}})
        return filter_clause

    def _genQuery(self, keywords, categories, filters, ids, from_, size_):
        must_clause = []
        should_clause = []
        filter_clause = []
        # filters['category'] = categories[0:4]
        if filters:
            filter_clause = self._addFilterClause(filter_clause, filters, 'selected', 'should')
            # filter_clause = self._add_filter_clause(filter_clause, filters, 'category', 'should')

        if keywords:
            must_clause.append(
                {
                    'multi_match': {
                        'analyzer': 'whitespace',
                        'query': ' '.join(keywords),
                        'fields': ['keywords', 'title_seg^3'],
                    }
                }
            )

        must_not_clause = {
            "bool": {"must_not": {"terms": {"id": ids}}}
        }

        filter_clause.append(must_not_clause)

        query = {"query": {
            "bool": {
                # "must": must_clause,
                # "should": should_clause,
                "filter": filter_clause,
                # "must": {'bool': {}},
                # "minimum_should_match": 1
            }
        }, 'from': from_, 'size': size_}

        if must_clause:
            query['query']['bool']['must'] = must_clause


        if should_clause:
            query['query']['bool']['should'] = should_clause

        return query

def extractResult(hit):
    source_ = hit['_source']
    return {
        'title': source_['title'],
        'url': source_['url'],
        'id': source_['id'],
        'biz_name': source_['biz_name'],
        'msg_cdn_url': source_['msg_cdn_url'],
        'read_num': source_['read_num'],
        'like_num': source_['like_num'],
        'publish_timestamp': source_['publish_timestamp'],
        'category': source_.get('category'),
    }